package com.bigknow.appstore.web.console.controller;

import com.bigknow.appstore.common.constants.DateFormatConstants;
import com.bigknow.appstore.web.base.vo.FancyTreeVo;
import com.bigknow.appstore.web.console.app.*;
import com.bigknow.appstore.web.console.service.*;
import com.bigknow.appstore.web.framework.controller.AbstractRestController;
import com.bigknow.appstore.web.framework.vo.ResultInfo;
import com.bigknow.appstore.web.framework.vo.VoFactory;
import com.bigknow.appstore.web.util.UploadFileUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.servlet.ModelAndView;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by 李科风 on 2016-09-28.
 */
@RestController
@RequestMapping("/sys/appView")
public class ApplicationViewController extends AbstractRestController<RecommendBanner, IRecommendBannerService> {

    @Autowired
    private IApplicationService appService;

    @Autowired
    private IApplicationCategoryService categoryService;

    @Autowired
    private ICommonApplicationService commonApplicationService;

    @Autowired
    private IRecommendApplicationService recommendApplicationService;

    @Override
    protected String getBasePath() {
        return "sys";
    }

    @Override
    protected String getBaseName() {
        return "appView";
    }

    @RequestMapping(value = "/list")
    public ModelAndView list(RecommendBanner t, Integer pageIndex, Integer pageSize) {
        ModelAndView mv = super.list(t, pageIndex, pageSize);
        Map<String, Object> model = new HashMap<>();
        mv.getModel().put("commonApps", getCommonApplicationDetail());
        mv.getModel().put("recommendApps", getRecommendApplicationDetail());

        return mv;
    }

    @RequestMapping("/getBannerApplicationTree")
    protected List<FancyTreeVo> getBannerApplicationTree(@RequestParam("id") String id) {
        List<String> ids = new ArrayList<>();
        if (!StringUtils.isEmpty(id)) {
            RecommendBanner banner = service.get(id);
            if (banner != null && banner.getApplications() != null) {
                ids.addAll(banner.getApplications());
            }
        }
        Application entity = new Application();
        entity.setState(ApplicationState.PUBLISHED);
        List<Application> apps = appService.findWithFuzzy(entity);
        Map<String, List<Application>> appMap = apps.stream().collect(Collectors.groupingBy(Application::getCategoryId));
        List<FancyTreeVo> res = new ArrayList<>();
        appMap.forEach((categoryId, appList) -> {
            ApplicationCategory category = categoryService.get(categoryId);
            if (category != null) {
                res.add(FancyTreeVo.toFancyTreeVo(category, vo -> {
                    vo.setKey(category.getId());
                    vo.setFolder(true);
                    vo.setExpanded(true);
                    vo.setTitle(category.getName());
                    vo.setChildren(FancyTreeVo.toFancyTreeVo(appList, (app, cvo) -> {
                        cvo.setKey(app.getId());
                        cvo.setTitle(app.getName());
                        cvo.setSelected(ids.contains(app.getId()));
                    }));
                }));
            }
        });

        return res;
    }

    @RequestMapping(value = "/rest/insertBanner", method = RequestMethod.POST)
    public ResultInfo insertBanner(@RequestParam("name") String name, @RequestParam("bannerFile") CommonsMultipartFile bannerFile, @RequestParam("sort") int sort, @RequestParam("applications") String applications) {
        RecommendBanner banner = new RecommendBanner();
        banner.setName(name);
        try {
            saveImage(bannerFile, banner);
        } catch (Exception e) {
            return VoFactory.newResultInfo(ResultInfo.ERROR, e.getMessage());
        }
        banner.setSort(sort);
        banner.setApplications(removeEmpty(applications));
        banner.setCreateTime(DateFormatConstants.getCurrentTime(DateFormatConstants.F_1));
        banner.setUpdateTime(DateFormatConstants.getCurrentTime(DateFormatConstants.F_1));

        return super.insert(banner);
    }

    @RequestMapping(value = "/rest/updateBanner", method = RequestMethod.POST)
    public ResultInfo updateBanner(@RequestParam("id") String id, @RequestParam("name") String name, @RequestParam("bannerFile") CommonsMultipartFile bannerFile, @RequestParam("sort") int sort, @RequestParam("applications") String applications) {
        RecommendBanner banner = service.get(id);
        banner.setName(name);
        try {
            if (bannerFile != null && !bannerFile.isEmpty()) {
                UploadFileUtils.deleteImage("/resource/banner", banner.getImgFile());
                saveImage(bannerFile, banner);
            }
        } catch (Exception e) {
            return VoFactory.newResultInfo(ResultInfo.ERROR, e.getMessage());
        }
        banner.setSort(sort);
        banner.setApplications(removeEmpty(applications));
        banner.setUpdateTime(DateFormatConstants.getCurrentTime(DateFormatConstants.F_1));

        return super.update(banner);
    }

    private void saveImage(@RequestParam("bannerFile") CommonsMultipartFile bannerFile, RecommendBanner banner) {
        String fileName = UploadFileUtils.saveImage(bannerFile, "/resource/banner", UUID.randomUUID().toString(), imgFile -> {
            if (imgFile.getWidth() != 1200 || imgFile.getHeight() != 340) {
                throw new RuntimeException("图像大小必须为1200px*340px");
            }
            return true;
        });
        banner.setImgFile(fileName);
    }

    @NotNull
    private List<String> removeEmpty(@RequestParam("applications") String applications) {
        return Arrays.asList(applications.split(",")).stream().filter(s -> !StringUtils.isEmpty(s)).collect(Collectors.toList());
    }

    @RequestMapping(value = "/rest/delete/{id}", method = RequestMethod.DELETE)
    public ResultInfo delete(@PathVariable String id) {
        RecommendBanner banner = service.get(id);
        UploadFileUtils.deleteImage("/resource/banner", banner.getImgFile());
        return super.delete(id);
    }

    @RequestMapping("/getCommonApplicationTree")
    public List<FancyTreeVo> getCommonApplicationTree() {
        CommonApplication commonApp = getCommonApplication();
        List<String> ids = commonApp.getApplications();
        Application entity = new Application();
        entity.setState(ApplicationState.PUBLISHED);
        List<Application> apps = appService.findWithFuzzy(entity);
        Map<String, List<Application>> appMap = apps.stream().collect(Collectors.groupingBy(Application::getCategoryId));
        List<FancyTreeVo> res = new ArrayList<>();
        appMap.forEach((categoryId, appList) -> {
            ApplicationCategory category = categoryService.get(categoryId);
            if (category != null) {
                res.add(FancyTreeVo.toFancyTreeVo(category, vo -> {
                    vo.setKey(category.getId());
                    vo.setFolder(true);
                    vo.setExpanded(true);
                    vo.setTitle(category.getName());
                    vo.setChildren(FancyTreeVo.toFancyTreeVo(appList.stream().filter(app -> !ids.contains(app.getId())).collect(Collectors.toList()), (app, cvo) -> {
                        cvo.setKey(app.getId());
                        cvo.setTitle(app.getName());
                    }));
                }));
            }
        });
        return res;
    }

    public synchronized CommonApplication getCommonApplication() {
        List<CommonApplication> list = commonApplicationService.findAll();
        CommonApplication commonApp = null;
        if (list.isEmpty()) {
            commonApp = new CommonApplication();
            commonApplicationService.insert(commonApp);
        } else {
            commonApp = list.get(0);
        }
        return commonApp;
    }

    @RequestMapping("/getCommonApplicationDetail")
    public List<Application> getCommonApplicationDetail() {
        CommonApplication commonApp = getCommonApplication();
        List<String> deletedApps = new ArrayList<>();
        List<Application> res = new ArrayList<>();
        for (String id : commonApp.getApplications()) {
            Application app = appService.get(id);
            if (app == null) {
                deletedApps.add(id);
            } else {
                res.add(app);
            }
        }
        if (!deletedApps.isEmpty()) {
            commonApp.getApplications().removeAll(deletedApps);
            commonApplicationService.update(commonApp);
        }
        return res;
    }

    @RequestMapping("/selectApp")
    public ModelAndView selectApp(@RequestParam("type") String type) {
        Map<String, String> model = new HashMap<>();
        model.put("type", type);
        return new ModelAndView("/sys/appView/selectApp", model);
    }

    @RequestMapping("/updateCommonApplication")
    public ResultInfo updateCommonApplication(@RequestParam("applications") String applications) {
        CommonApplication commonApp = getCommonApplication();
        for (String appId : applications.split(",")) {
            if (!StringUtils.isEmpty(appId) && !commonApp.getApplications().contains(appId)) {
                commonApp.getApplications().add(appId);
            }
        }

        commonApplicationService.update(commonApp);
        return VoFactory.newResultInfo(ResultInfo.SUCCESS, "添加成功");
    }

    @RequestMapping("/delCommonApplication")
    public ResultInfo delCommonApplication(@RequestParam("id") String id) {
        CommonApplication commonApp = getCommonApplication();
        commonApp.getApplications().remove(id);

        commonApplicationService.update(commonApp);
        return VoFactory.newResultInfo(ResultInfo.SUCCESS, "删除成功");
    }

    @RequestMapping("/resortCommonApplication")
    public ResultInfo resortCommonApplication(@RequestParam("applications") String applications) {
        CommonApplication commonApp = getCommonApplication();
        commonApp.getApplications().clear();
        for (String appId : applications.split(",")) {
            commonApp.getApplications().add(appId);
        }

        commonApplicationService.update(commonApp);
        return VoFactory.newResultInfo(ResultInfo.SUCCESS, "更新成功");
    }

    @RequestMapping("/getRecommendApplicationTree")
    public List<FancyTreeVo> getRecommendApplicationTree() {
        RecommendApplication recommendApp = getRecommendApplication();
        List<String> ids = recommendApp.getApplications();
        Application entity = new Application();
        entity.setState(ApplicationState.PUBLISHED);
        List<Application> apps = appService.findWithFuzzy(entity);
        Map<String, List<Application>> appMap = apps.stream().collect(Collectors.groupingBy(Application::getCategoryId));
        List<FancyTreeVo> res = new ArrayList<>();
        appMap.forEach((categoryId, appList) -> {
            ApplicationCategory category = categoryService.get(categoryId);
            if (category != null) {
                res.add(FancyTreeVo.toFancyTreeVo(category, vo -> {
                    vo.setKey(category.getId());
                    vo.setFolder(true);
                    vo.setExpanded(true);
                    vo.setTitle(category.getName());
                    vo.setChildren(FancyTreeVo.toFancyTreeVo(appList.stream().filter(app -> !ids.contains(app.getId())).collect(Collectors.toList()), (app, cvo) -> {
                        cvo.setKey(app.getId());
                        cvo.setTitle(app.getName());
                    }));
                }));
            }
        });
        return res;
    }

    public synchronized RecommendApplication getRecommendApplication() {
        List<RecommendApplication> list = recommendApplicationService.findAll();
        RecommendApplication recommendApp = null;
        if (list.isEmpty()) {
            recommendApp = new RecommendApplication();
            recommendApplicationService.insert(recommendApp);
        } else {
            recommendApp = list.get(0);
        }
        return recommendApp;
    }

    @RequestMapping("/getRecommendApplicationDetail")
    public List<Application> getRecommendApplicationDetail() {
        RecommendApplication recommendApp = getRecommendApplication();
        List<String> deletedApps = new ArrayList<>();
        List<Application> res = new ArrayList<>();
        for (String id : recommendApp.getApplications()) {
            Application app = appService.get(id);
            if (app == null) {
                deletedApps.add(id);
            } else {
                res.add(app);
            }
        }
        if (!deletedApps.isEmpty()) {
            recommendApp.getApplications().removeAll(deletedApps);
            recommendApplicationService.update(recommendApp);
        }
        return res;
    }

    @RequestMapping("/updateRecommendApplication")
    public ResultInfo updateRecommendApplication(@RequestParam("applications") String applications) {
        RecommendApplication recommendApp = getRecommendApplication();
        for (String appId : applications.split(",")) {
            if (!StringUtils.isEmpty(appId) && !recommendApp.getApplications().contains(appId)) {
                recommendApp.getApplications().add(appId);
            }
        }

        recommendApplicationService.update(recommendApp);
        return VoFactory.newResultInfo(ResultInfo.SUCCESS, "添加成功");
    }

    @RequestMapping("/delRecommendApplication")
    public ResultInfo delRecommendApplication(@RequestParam("id") String id) {
        RecommendApplication recommendApp = getRecommendApplication();
        recommendApp.getApplications().remove(id);

        recommendApplicationService.update(recommendApp);
        return VoFactory.newResultInfo(ResultInfo.SUCCESS, "添加成功");
    }

    @RequestMapping("/resortRecommendApplication")
    public ResultInfo resortRecommendApplication(@RequestParam("applications") String applications) {
        RecommendApplication recommendApp = getRecommendApplication();
        recommendApp.getApplications().clear();
        for (String appId : applications.split(",")) {
            recommendApp.getApplications().add(appId);
        }

        recommendApplicationService.update(recommendApp);
        return VoFactory.newResultInfo(ResultInfo.SUCCESS, "更新成功");
    }
}
